iT邦幫忙

2026 iThome 鐵人賽

DAY 28
0
Modern Web

從 UI/UX 設計到前端實作:30 天打造專屬的任務學習計時器系列 第 28 篇

DAY 28|使用者體驗優化(二):多國語系(i18n)切換與語系狀態持久化

  • 分享至 

  • xImage
  •  

隨著功能逐漸完善,產品目前已經具備了完整的計時與任務管理能力。
接下來,為了讓更多不同語言的使用者也能無縫使用,要在 Header 加入多國語系切換選單,支援 繁體中文 (zh-TW)、英文 (en)、日文 (ja) 三種語言。


一、 多國語系(i18n)的核心設計思路

在不使用複雜前端框架(如 React-i18next 或 Vue-i18n)的前提下,用 Vanilla JS 實作出乾淨、高效的多國語系機制:

  1. JSON / Object 字典檔:定義每一種語言對應的文字對照表(Dictionary)。

  2. data-i18n 屬性標記:在 HTML 標籤上加上 data-i18n="key",方便 JS 自動掃描並替換文字。

  3. 語系切換器(Language Switcher):在 Header 放入 <select>,讓使用者隨時切換。

  4. 狀態持久化:將使用者的語系偏好儲存在 localStorage,下次開啟頁面時自動載入。


二、 建立語系字典檔(i18n.js)

首先建立一個字典物件,將介面上常用的固定文字統一管理:

const translations = {
  'zh-TW': {
    appName: '任務計時器',
    startTimer: '開始計時',
    pauseTimer: '暫停',
    resumeTimer: '繼續',
    stopTimer: '結束並儲存',
    subtaskNotStarted: '未開始',
    subtaskInProgress: '進行中',
    subtaskCompleted: '已完成',
    idleAlertTitle: '閒置提醒',
    offlineNotice: '目前處於離線狀態,您的資料仍會安全儲存在本地!'
  },
  'en': {
    appName: 'TaskTimer',
    startTimer: 'Start',
    pauseTimer: 'Pause',
    resumeTimer: 'Resume',
    stopTimer: 'Stop & Save',
    subtaskNotStarted: 'Not Started',
    subtaskInProgress: 'In Progress',
    subtaskCompleted: 'Completed',
    idleAlertTitle: 'Idle Alert',
    offlineNotice: 'You are currently offline. Your data is stored locally!'
  },
  'ja': {
    appName: 'TaskTimer',
    startTimer: '開始',
    pauseTimer: '一時停止',
    resumeTimer: '再開',
    stopTimer: '終了して保存',
    subtaskNotStarted: '未着手',
    subtaskInProgress: '進行中',
    subtaskCompleted: '完了',
    idleAlertTitle: '無操作警告',
    offlineNotice: '現在オフラインです。データはローカルに保存されます!'
  }
};

三、 Header 下拉選單 HTML

在 Header 區域加入語系切換的 <select> 選單:

<div class="d-flex align-items-center">
    <!-- 語系切換選單 -->
    <select 
      id="languageSelect" 
      class="form-select form-select-sm border-secondary-subtle rounded-pill"
      style="width: auto; cursor: pointer;"
      onchange="changeLanguage(this.value)"
    >
      <option value="zh-TW">繁體中文</option>
      <option value="en">English</option>
      <option value="ja">日本語</option>
    </select>
</div

四、 語系切換核心邏輯

透過 changeLanguage() 函式更新畫面上的文字,並將偏好記錄在 localStorage:

// 預設語系:優先讀取 localStorage,若無則讀取瀏覽器預設語系,最後退回繁體中文
let currentLang = localStorage.getItem('app_lang') || navigator.language || 'zh-TW';

// 初始化時校正語系名稱(例如 en-US 轉成 en)
if (!translations[currentLang]) {
  if (currentLang.startsWith('en')) currentLang = 'en';
  else if (currentLang.startsWith('ja')) currentLang = 'ja';
  else currentLang = 'zh-TW';
}

function changeLanguage(lang) {
  if (!translations[lang]) return;
  
  currentLang = lang;
  localStorage.setItem('app_lang', lang);

  // 1. 更新有 data-i18n 屬性的靜態 HTML 文字
  document.querySelectorAll('[data-i18n]').forEach(element => {
    const key = element.getAttribute('data-i18n');
    if (translations[lang][key]) {
      element.textContent = translations[lang][key];
    }
  });

  // 2. 重新渲染動態產生的 UI(如任務清單與子任務狀態選單)
  renderTaskAccordion();
  
  // 3. 更新 Header 下拉選單本身的選取狀態
  document.getElementById('languageSelect').value = lang;
}

// 頁面載入後自動套用語系
document.addEventListener('DOMContentLoaded', () => {
  changeLanguage(currentLang);
});

語言切換


小結

加上 i18n 多國語系後,不再受限於單一語言,不論是繁體中文、英文還是日文使用者,都能享有一致的介面體驗。同時透過 localStorage 記憶使用者的選擇,讓使用者在每次開啟系統時都保有極佳的連續性。


上一篇
DAY 27|使用者體驗優化(一):閒置提醒、離線狀態偵測、隱藏/顯示秒數切換
下一篇
DAY 29|使用者體驗優化(三):打造舒適的暗色模式(Dark Mode)體驗
系列文
從 UI/UX 設計到前端實作:30 天打造專屬的任務學習計時器 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言